我們經常會使用這些型別各自的方法, 例如用 length
取得字串的長度。
但為什麼明明是 基本型別 卻會有 屬性 以及 方法 可以呼叫?
這是因為這些型別有著相對應的 包裹物件 (Primitive Wrapper),這些 包裹物件 包含了這些物件可以使用的方法,我們接著會在物件型別中做更多說明。
先來看關於原始型別的範例程式碼:
let a, b, c, d, e;
a = 1; //number
b = '文字'; //string
c = true; //boolean
d = {}; //object
e = null; //object
console.log(typeof(a));
console.log(f); // VM1420:1 Uncaught ReferenceError: e is not defined
console.log(typeof(f)); // undefined
值得注意的是:
null
,但型別卻是 object
,這是 js 長久以來的一個錯誤,沒有修正是因為許多的網站也使用了這樣的錯誤觀念完成了網站。如果修正的話會造成許多的網站因此而壞掉,所以就把這個錯誤保留了下來。undefined
, 這是 typeof
保護機制,如果在沒有定義 f 這個變數的情境下 console.log
的話,會出現的是 not defined
現在來看另一段範例:
let a = 'ming ';
console.log(a.length); // 5
console.log(a.toUpperCase()); // MING
console.log(a.trim()); // ming
上述這些方法都是針對字串所做的,但是直接 console.log(a)
; 也只有顯示 'ming ',並沒有顯示那些可以用的方法,而 包裹物件 則可以做得到。
前面提到,基本型別會有「屬性」以及「方法」是因為這些型別有著相對應的包裹物件 (Primitive Wrapper)。
也就是「自動轉型」賦予 String
、Number
與 Boolean
這些神奇的功能。
在 JavaScript 這門程式語言當中,當我們嘗試著要去存取 String
、Number
與 Boolean
這三種基本型別的屬性時,它就只會在「那一刻」被轉型為該類別的「物件」。
let a = 'ming ';
console.log(a.length);
上面段程式碼,當我們試著去讀取 a.length
的時候,背後原理是這樣的:
let a = new String('ming ');
a.length;
a = null;
a = 'ming ';
它會透過對應的物件建構器將 'ming ' 包裝成一個 String 的「物件」,然後回傳對應的屬性後,即刻銷毀恢復成基本型別。
我們可以透過下面這段程式碼來了解 原始型別 與 物件型別 的不同。
let a = 'ming ';
let e = new String(a);
console.log(a, e);
我們可以透過下面這段程式碼來了解 原始型別 與 物件型別 的不同。
透過這樣的方式宣告之後,來看看執行的結果:
可以看到 [[prototype]] 就是 e 這個包裹物件的可以用的方法總集
同樣可以套用原是型別的字串身上,所以我們剛剛用的 trim
lengthto
UpperCase
都在這裡面喔!
然而,其實並不建議在宣告字串的時候使用字串的 包裹物件 方式宣告,這種宣告方式又稱為 建構式
後續的篇章會講到,而不建議的最大重點在於,透過建構式宣告出來的變數資料型別不會是字串,而是 物件 喔!